#include "stdafx.h"
#include "Control.h"

namespace sf
{
std::ostream& operator<<(std::ostream& stream, Color& color)
{
		stream
				<< std::setfill('0')
				<< "#"
				<< std::hex
				<< std::setw(2) << static_cast<int>(color.r)
				<< std::setw(2) << static_cast<int>(color.g)
				<< std::setw(2) << static_cast<int>(color.b)
				<< std::setw(2) << static_cast<int>(color.a)
				<< std::dec
		;
		return stream;
}

std::istream& operator>>(std::istream& stream, Color& color)
{
		std::string buffer;
		stream >> buffer;
		// Check length and leading '#'.
		if( buffer.size() != 9 || buffer[0] != '#' ) {
				stream.setstate( std::ios::failbit );
				return stream;
		}
		std::stringstream r( buffer.substr( 1, 2 ) );
		std::stringstream g( buffer.substr( 3, 2 ) );
		std::stringstream b( buffer.substr( 5, 2 ) );
		std::stringstream a( buffer.substr( 7, 2 ) );
		int r_val( 0 );
		int g_val( 0 );
		int b_val( 0 );
		int a_val( 0 );

		r >> std::hex >> r_val;
		g >> std::hex >> g_val;
		b >> std::hex >> b_val;
		a >> std::hex >> a_val;

		color.r = static_cast<sf::Uint8>( r_val );
		color.g = static_cast<sf::Uint8>( g_val );
		color.b = static_cast<sf::Uint8>( b_val );
		color.a = static_cast<sf::Uint8>( a_val );
		return stream;
}
std::ostream& operator<<(std::ostream& stream, Vector2u& vector)
{
	stream
			<< std::setfill('0')
			<< vector.x
			<< "#"
			<< vector.y
	;
	return stream;
}
std::istream& operator>>(std::istream& stream, Vector2u& vector)
{
	std::string buffer;
	stream >> buffer;
	std::size_t found = buffer.find_first_of("#");
	if (found == std::string::npos)
	{
		stream.setstate(std::ios::failbit);
		return stream;
	}
	std::stringstream x(buffer.substr(0, found));
	std::stringstream y(buffer.substr(found + 1));

	x >> vector.x;
	y >> vector.y;

	return stream;
}
std::ostream& operator<<(std::ostream& stream, Vector2i& vector)
{
	stream
			<< std::setfill('0')
			<< vector.x
			<< "#"
			<< vector.y
	;
	return stream;
}
std::istream& operator>>(std::istream& stream, Vector2i& vector)
{
	std::string buffer;
	stream >> buffer;
	std::size_t found = buffer.find_first_of("#");
	if (found == std::string::npos)
	{
		stream.setstate(std::ios::failbit);
		return stream;
	}
	std::stringstream x(buffer.substr(0, found - 1));
	std::stringstream y(buffer.substr(found + 1));

	x >> vector.x;
	y >> vector.y;

	return stream;
}
}

Control::Control(Control::Ptr parent /* =  nullptr */)
	: m_parent(parent)
{
	m_independentProperties.push_back("Size");
}

Control::~Control()
{
	m_propertyMap.clear();
	m_independentProperties.clear();
}

template <typename T>
void Control::setValue(std::string propName, T value)
{
	std::stringstream stream;
	stream << value;
	m_propertyMap[propName] = stream.str();
}

void Control::setValue(std::string propName, std::string value)
{
	m_propertyMap[propName] = value;
}

template <typename T>
T Control::getValue(std::string propName)
{
	static T default_ = T();

	T result = T();

	std::string value;
	PropertyMap::iterator it = m_propertyMap.find(propName);
	if (it != m_propertyMap.end())
	{
		value = it->second;
		std::stringstream valueStream(value);
		valueStream >> result;
	}
	else if (m_parent != nullptr)
	{
		if (std::find(m_independentProperties.begin(), m_independentProperties.end(), propName) == m_independentProperties.end())
			result = m_parent->getValue<T>(propName);
	}
	
	return result;
}

std::string Control::getValue(std::string propName)
{
	std::string result;

	PropertyMap::iterator it = m_propertyMap.find(propName);
	if (it != m_propertyMap.end())
		result = it->second;
	else if (m_parent != nullptr)
	{
		if (std::find(m_independentProperties.begin(), m_independentProperties.end(), propName) == m_independentProperties.end())
			result = m_parent->getValue(propName);
	}

	return result;
}

//props
void Control::setWidth(unsigned int width)
{
	sf::Vector2u size = getValue<sf::Vector2u>("Size");
	size.x = width;
	setValue("Size", size);
}

unsigned int Control::getWidth()
{
	sf::Vector2u size = getValue<sf::Vector2u>("Size");
	return size.x;
}

void Control::setHeight(unsigned int height)
{
	sf::Vector2u size = getValue<sf::Vector2u>("Size");
	size.y = height;
	setValue("Size", size);
}

unsigned int Control::getHeight()
{
	sf::Vector2u size = getValue<sf::Vector2u>("Size");
	return size.y;
}